﻿using System.Net;
using System.Web.Script.Serialization;
using D3DSS.DataContract;
using D3DSS.IDomain;
using D3DSS.Model;
using D3DSS.Utility;
using System;
using D3DSS.IRepository;
using System.Collections.Generic;

namespace D3DSS.Domain
{
    /// <summary>
    /// 账号领域服务
    /// </summary>
    public class Account : IAccount
    {
        /// <summary>
        /// 账户仓储接口
        /// </summary>
        protected IRepository<AccountModel> AccountRepository { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        public Account(IRepository<AccountModel> accountRepository)
        {
            AccountRepository = accountRepository;
        }

        /// <summary>
        /// 注册
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public Response<RegisterResponse> Register(RegisterRequest request)
        {
            var response = new Response<RegisterResponse>();
            response.Data = new RegisterResponse();

            response.MessageDictionary = new List<Message>();
            Message message = new Message();
            message.MessageCode = "0000";
            message.MessageContent = "服务器忙，请稍后再试！";
            response.MessageDictionary.Add(message);

            message = new Message();
            message.MessageCode = "1000";
            message.MessageContent = "该邮箱已被使用！";

            response.MessageDictionary.Add(message);
            
            try
            {
                var account = AccountRepository.Single(a => a.Account == request.Account);
                if (account == null)
                {
                    account = new AccountModel();
                    account.Account = request.Account;
                    account.Password = request.Password;
                    account.CreateTime = DateTime.Now;
                    account.ID = AccountRepository.Add(account).ID;

                    var token = new Token();
                    token.UserID = account.ID;
                    token.Sign = TokenHelper.CreateSign(token.UserID, account.Account, account.Password);
                    CacheManager.Set(CacheRegion.Sign, token.UserID, token, ConfigHelper.GetAppSetting<int>("SignExpireMinute"));
                    response.Data.Token = token;
                    response.IsSuccess = true;
                }
                else
                {
                    response.Code = "1000";
                }
            }
            catch
            {
                response.Code = "0000";
            }

            return response;
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public Response<LoginResponse> Login(LoginRequest request)
        {
            var response = new Response<LoginResponse>();
            response.Data = new LoginResponse();

            response.MessageDictionary = new List<Message>();
            Message message = new Message();
            message.MessageCode = "0000";
            message.MessageContent = "服务器忙，请稍后再试！";
            response.MessageDictionary.Add(message);

            message = new Message();
            message.MessageCode = "1000";
            message.MessageContent = "邮箱或者密码错误！";

            response.MessageDictionary.Add(message);

            try
            {
                var account = AccountRepository.Single(a => a.Account == request.Account && a.Password == request.Password);
                if (account != null)
                {
                    var token = CacheManager.Get<Token>(CacheRegion.Sign, account.ID);
                    if (token == null)
                    {
                        token = new Token();
                        token.UserID = account.ID;
                        token.Sign = TokenHelper.CreateSign(token.UserID, account.Account, account.Password);
                        CacheManager.Set(CacheRegion.Sign, token.UserID, token, ConfigHelper.GetAppSetting<int>("SignExpireMinute"));
                    }
                    response.Data.Token = token;
                    response.IsSuccess = true;
                }
                else
                {
                    response.Code = "1000";
                }
            }
            catch
            {
                response.Code = "0000";
            }
            return response;
        }

        /// <summary>
        /// 处理授权
        /// </summary>
        /// <param name="authorization"></param>
        /// <returns></returns>
        public Response<AuthorizationInfo> ProcessAuthorization(string authorization)
        {
            var response = new Response<AuthorizationInfo>();
            response.Data = new AuthorizationInfo();
            response.Data.StatusCode = HttpStatusCode.OK;

            if (!string.IsNullOrEmpty(authorization))
            {
                var serializer = new JavaScriptSerializer();
                var tokenClient = serializer.Deserialize<Token>(authorization);
                var tokenServer = GetServerToken(tokenClient.UserID);
                if (tokenServer == null)
                {
                    response.Data.StatusCode = HttpStatusCode.Unauthorized;
                }
                else
                {
                    response.Data.StatusCode = tokenClient.Sign.Equals(tokenServer.Sign) ? HttpStatusCode.OK : HttpStatusCode.NonAuthoritativeInformation;
                }
            }
            else
            {
                response.Data.StatusCode = HttpStatusCode.MethodNotAllowed;
            }
            response.IsSuccess = response.Data.StatusCode == HttpStatusCode.OK;
            return response;
        }

        /// <summary>
        /// 获取服务端通行证
        /// </summary>
        /// <param name="tokenClient"></param>
        /// <returns></returns>
        private Token GetServerToken(int userID)
        {
            var tokenServer = CacheManager.Get<Token>(CacheRegion.Sign, userID);
            if (tokenServer == null)
            {
                var account = AccountRepository.Single(a => a.ID == userID);

                if (account != null)
                {
                    tokenServer = new Token();
                    tokenServer.UserID = userID;
                    tokenServer.Sign = TokenHelper.CreateSign(account.ID, account.Account, account.Password);
                    CacheManager.Set(CacheRegion.Sign, tokenServer.UserID, tokenServer, ConfigHelper.GetAppSetting<int>("SignExpireMinute"));
                }
            }
            return tokenServer;
        }
    }
}
